package com.lmind.core.gps.alone;

import java.net.SocketAddress;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lmind.core.async.ResultHandler;
import com.lmind.core.gis.Location;
import com.lmind.core.gps.terminal.DefaultMessageCodec;
import com.lmind.core.gps.terminal.message.AbstractMessage;
import com.lmind.core.gps.terminal.message.AccessMessage;
import com.lmind.core.gps.terminal.message.KeepAliveMessage;
import com.lmind.core.gps.terminal.message.LocateMessage;
import com.lmind.core.gps.terminal.message.LocationMessage;
import com.lmind.core.gps.terminal.message.ReplyMessage;
import com.lmind.core.message.MessageServiceListener;
import com.lmind.core.message.MessagePipe;
import com.lmind.core.message.MessagePipeIoHandler;
import com.lmind.core.message.MessagePipeIoHandlerConfig;
import com.lmind.core.message.PipelineManager;
import com.lmind.core.message.RequestResponseProcessor;
import com.lmind.support.etc.Interval;

public class VirtualTerminal implements MessageServiceListener, RequestResponseProcessor {
	
	private static final Logger logger = LoggerFactory.getLogger(VirtualTerminal.class);
	
	private NioSocketConnector connector;
	
	private MessagePipeIoHandler messagePipe;
	
	private PipelineManager messageHelper;
	
	private MessagePipe pipe;
	
	private String deviceSerial;
	
	private ScheduledExecutorService executorService;
	
	private long timeTick = 1000 * 10;
	
	/** 上报位置间隔 */
	private Interval locationInterval;
	
	/** 上报位置间隔 */
	private long interval;
	
	/** 开始位置 */
	private Location location;
	
	/** 开始时间 */
	private long startTime = System.currentTimeMillis();
	
	/** 速度 */
	private double speed = 0.0001;
	
	/** 方向,单位弧度 */
	private double direction = 0;

	public VirtualTerminal() {
		
		MessagePipeIoHandlerConfig config = new MessagePipeIoHandlerConfig();
		config.setKeepAliveTime(5);
		
		connector = new NioSocketConnector();
		messagePipe = new MessagePipeIoHandler();
		
		connector.setHandler(messagePipe);
		
		messagePipe.setIoService(connector);
		messagePipe.setConfig(config);
		messagePipe.setCodec(new DefaultMessageCodec());
		messagePipe.addMessageServiceListener(this);
		
		messageHelper = new PipelineManager();
		messageHelper.setMessagePipe(messagePipe);
		messageHelper.setMessageProcessor(this);
		
		messagePipe.init();
		messageHelper.init();
	}

	public String getDeviceSerial() {
		return deviceSerial;
	}

	public void setDeviceSerial(String deviceSerial) {
		this.deviceSerial = deviceSerial;
	}

	public Location getLocation() {
		return location;
	}

	public void setLocation(Location location) {
		this.location = location;
	}
	
	public void setInterval(long interval) {
		this.interval = interval;
	}

	public ScheduledExecutorService getExecutorService() {
		return executorService;
	}

	public void setExecutorService(ScheduledExecutorService executorService) {
		this.executorService = executorService;
	}

	public void connect(SocketAddress address) {
		connector.connect(address);
	}
	
	public void close() {
		connector.dispose(true);
		messageHelper.close();
	}
	
	@Override
	public void connected(MessagePipe pipe) {
		
		this.pipe = pipe;
		
		AccessMessage access = new AccessMessage(deviceSerial);
		messageHelper.send(pipe, access, new ResultHandler<Object>() {
			public void result(Object result) {
				ReplyMessage reply = (ReplyMessage)result;
				logger.debug(reply.toString());
			}
			public void exception(Throwable e) {
			}
		});
		
		if (interval != 0) {
			executorService.scheduleAtFixedRate(new Runnable() {
				@Override
				public void run() {
					try {
						onTime();
					} catch (Exception e) {
						logger.error("执行定时上位置时失败", e);
					}
				}
			}, 0, interval, TimeUnit.MILLISECONDS);
		}
		
		
//		executorService.schedule(new Runnable() {
//			@Override
//			public void run() {
//				onTime();
//				executorService.schedule(this, timeTick, TimeUnit.MILLISECONDS);
//			}
//		}, timeTick, TimeUnit.MILLISECONDS);
	}

	@Override
	public void disconnected(MessagePipe pipe) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void message(MessagePipe pipe, Object message) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keepAlive(MessagePipe pipe) {
		pipe.send(new KeepAliveMessage());
	}

	@Override
	public boolean isRequest(MessagePipe pipe, Object message) {
		return ((AbstractMessage)message).hasResponse();
	}

	@Override
	public boolean isResponse(MessagePipe pipe, Object message) {
		return message instanceof ReplyMessage;
	}

	@Override
	public void process(MessagePipe pipe, Object message,
			ResultHandler<Object> handler) {
		
		logger.debug("虚拟终端接收到指令" + message);
		if (message instanceof LocateMessage) {
			pipe.send(locate(System.currentTimeMillis() - startTime));
		}
	}
	
	protected void onTime() {
		long now = System.currentTimeMillis();
		pipe.send(locate(now - startTime));
	}
	
	protected LocationMessage locate(long duration) {
		// 位移
		double s = speed * duration / 1000;
		double longitude = location.getLongitude() + s * Math.cos(direction);
		double latitude = location.getLatitude() + s * Math.sin(direction);
		return new LocationMessage(new Location(latitude, longitude));
	}
}
